package crp.core.security;

import com.google.common.base.Objects;
import com.qwlabs.cdi.SafeCDI;
import com.qwlabs.lang.F2;
import com.qwlabs.security.AnonymousCaller;
import com.qwlabs.security.Caller;
import com.qwlabs.security.CallerPrincipal;
import crp.core.user.domain.models.UserEntity;
import io.quarkus.security.identity.SecurityIdentity;
import org.checkerframework.checker.nullness.qual.Nullable;

import javax.enterprise.inject.Instance;

public final class Callers {
    private static final String TYPE_CLIENT = "CLIENT";
    private static final String TYPE_USER = "USER";
    public static final String ATTRIBUTE_USER_ID = "USER_ID";
    public static final String ATTRIBUTE_STUDENT_ID = "STUDENT_ID";
    public static final String ATTRIBUTE_FACULTY_ID = "FACULTY_ID";
    public static final String ATTRIBUTE_USER = "USER";

    private Callers() {
    }

    public static boolean isClient(@Nullable String type) {
        return Objects.equal(type, TYPE_CLIENT);
    }

    public static boolean isUser(@Nullable String type) {
        return Objects.equal(type, TYPE_USER);
    }

    public static boolean isClient(@Nullable Caller caller) {
        return F2.ifPresent(caller, c -> (Boolean) c.is(TYPE_CLIENT));
    }

    public static boolean isUser(@Nullable Caller caller) {
        return F2.ifPresent(caller, c -> (Boolean) c.is(TYPE_USER));
    }

    public static String userId(@Nullable Caller caller) {
        return F2.ifPresent(caller, c -> (String) c.attribute(ATTRIBUTE_USER_ID));
    }

    public static String userId() {
        return userId(current());
    }

    public static UserEntity user(Caller caller) {
        return F2.ifPresent(caller, c -> (UserEntity) c.attribute(ATTRIBUTE_USER));
    }

    public static UserEntity user() {
        return user(current());
    }

    public static String studentId(@Nullable Caller caller) {
        return F2.ifPresent(caller, c -> (String) c.attribute(ATTRIBUTE_STUDENT_ID));
    }

    public static String studentId() {
        return studentId(current());
    }

    public static String facultyId(@Nullable Caller caller) {
        return F2.ifPresent(caller, c -> (String) c.attribute(ATTRIBUTE_FACULTY_ID));
    }

    public static String facultyId() {
        return studentId(current());
    }

    public static Caller current() {
        return SafeCDI.select(SecurityIdentity.class)
                .map(Instance::get)
                .map(Caller::load)
                .orElse(AnonymousCaller.INSTANCE);
    }

    public static CallerPrincipal fromUser(String userId) {
        return new CallerPrincipal(userId, TYPE_USER);
    }

    public static CallerPrincipal fromServer(String orgId) {
        return new CallerPrincipal(orgId, TYPE_CLIENT);
    }


}
